/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package se.kth.lwr.jeat.samples.onsitetreatment;

import javax.measure.quantity.Duration;
import javax.measure.quantity.Length;
import javax.measure.unit.NonSI;
import javax.measure.unit.SI;
import javax.measure.unit.Unit;
import org.jscience.physics.amount.Amount;
import se.kth.lwr.jeat.core.*;
import se.kth.lwr.jeat.samples.onsitetreatment.producers.ConcreteProducer;
import se.kth.lwr.jeat.samples.onsitetreatment.producers.ReinforcementProducer;
import se.kth.lwr.jeat.samples.onsitetreatment.transportations.SewageLorry;

/**
 *
 * @author davidev
 */
public class SepticTank extends WasteWaterTreatmentUnit {

    public SepticTank(String name, String description) {
        super(name, description);
        addSubActivities();
    }

    private void addSubActivities() {
        //compute the amount of different components
        AmountFunction kgConcrete = new AmountFunction(septicTankWeight).multiply(concreteContentSepticTank);
        AmountFunction kgReinforcement = new AmountFunction(septicTankWeight).multiply(reinforcementContentSepticTank);
        //AmountFunction kgSteelFeeber = new AmountFunction(septicTankWeight).multiply(steelFiberContentSepticTank);
        
        // prepare a complete sourcefunction
        kgConcrete.divide(lifetimeSepticTank).divide(Scenario1.systemUsers);
        // add production of concrete 
        addChild(ConcreteProducer.getInstance().getProduction("concrete production",
                "production of concrete for septic tank",
                kgConcrete));
        
        // perepare a completet sourcefunction
        AmountFunction reinforcementMultiplier = kgReinforcement.divide(lifetimeSepticTank).divide(Scenario1.systemUsers);
        // add production of concrete
        addChild(ReinforcementProducer.getInstance().getProduction("reinforcement production",
                "production of reinforcement for concrete septic tank",
                reinforcementMultiplier));
        // add transports for septic tank emptying
        setupSepticTankTransports();

        
    }
    
    private void setupSepticTankTransports(){
        //caclulate number of users
        AmountFunction users=new AmountFunction(Scenario1.systemUsers).multiply(householdNrSewageLorry);
        //create lorry
        SewageLorry lorry = new SewageLorry(septicEmptyingIntervall, users);
        //make all calculations on 50% fill degree
        lorry.setFill(0.5);
        //start ride to area
        lorry.transport((Amount<Length>) Amount.valueOf("30 km"), "ride to working area");
        //create a separate route to loop in the area
        SewageLorry loop=new SewageLorry(septicEmptyingIntervall, users);
        loop.setFill(0.5);
        loop.transport((Amount<Length>) Amount.valueOf("0.5 km"),"ride to tank");
        loop.idle((Amount<Duration>)Amount.valueOf("20 min"),"Empty tank");
        
        // repeat the loop 20 times before going back
        lorry.repeatRoutSequence(loop, 20);
        // ride home
        lorry.transport((Amount<Length>) Amount.valueOf("30 km"), "ride back to wastewater treatment plant");
        //discharge
        lorry.idle((Amount<Duration>) Amount.valueOf("10 min"), "Empty lorry");
        //create the activity
        Activity transport = lorry.getRouteActivity("Transport", "Transport route for septic tank emptying");
        //join MAINTAINANCE_PHASE
        transport.joinCategoryDeep(ActivityCategory.MAINTAINANCE_PHASE);
        //add to this activity
        addChild(transport);
        
    }

    /**Treatment of incoming wastewater
     * 
     * @param inventory wastewater inventory from pre treatment unit
     * @return wastewater from this unit
     */
    @Override
    protected Inventory processWasteWaterInventory(Inventory inventory) {
        Amount P_removal = inventory.getEmissionToWater(EmissionCategory.P).times(P_removal_rate.useValue(this));
        Amount N_removal = inventory.getEmissionToWater(EmissionCategory.N).times(N_removalrate.useValue(this));
        Amount BOD_removal = inventory.getEmissionToWater(EmissionCategory.BOD7).times(BOD7_removalrate.useValue(this));

        inventory.addEmissionToWater(EmissionCategory.P, P_removal.opposite());
        inventory.addEmissionToWater(EmissionCategory.N, N_removal.opposite());
        inventory.addEmissionToWater(EmissionCategory.BOD7, BOD_removal.opposite());
        return inventory;
    }

    @Override
    public Inventory contribute(Inventory inventory) {
        return inventory;
    }
    /**
     * Repeat time for septic tank emptying
     * <p/>
     * Value: 1.0
     * <p/>
     * Unit: year
     */
    public static final AmountDataSource septicEmptyingIntervall = new AmountDataSource<>(
            "septicEmptyingIntervall",
            "Repeat time for septic tank emptying",
            Amount.valueOf(1.0, NonSI.YEAR));
    /**
     * Total weight septic tank
     * <p/>
     * Value: 2560
     * <p/>
     * Unit: kg
     */
    public static final DataSource<Amount> septicTankWeight = new AmountDataSource(
            "septicTankWeight",
            "Total weight septic tank",
            Amount.valueOf(2560, SI.KILOGRAM));
    /**
     * Conretet content in septic tank
     * <p/>
     * Value: 99
     * <p/>
     * Unit: %
     */
    public static final DataSource<Amount> concreteContentSepticTank = new AmountDataSource(
            "concreteContentSepticTank",
            "Conretet content in septic tank",
            Amount.valueOf(99, NonSI.PERCENT));
    /**
     * Reinforcement content in septic tank
     * <p/>
     * Value: 0.4
     * <p/>
     * Unit: %
     */
    public static final AmountDataSource reinforcementContentSepticTank = new AmountDataSource<>(
            "reinforcementContentSepticTank",
            "Reinforcement content in septic tank",
            Amount.valueOf(0.4, NonSI.PERCENT));
    /**
     * Steel fiber content in septic tank
     * <p/>
     * Value: 1.3
     * <p/>
     * Unit: %
     */
    public static final AmountDataSource steelFiberContentSepticTank = new AmountDataSource<>(
            "steelFiberContentSepticTank",
            "Steel fiber content in septic tank",
            Amount.valueOf(1.3, NonSI.PERCENT));
    /**
     * Lifetime of septic tank
     * <p/>
     * Value: 30
     * <p/>
     * Unit: year
     */
    public static final AmountDataSource lifetimeSepticTank = new AmountDataSource<>(
            "lifetimeSepticTank",
            "Lifetime of septic tank",
            Amount.valueOf(30, NonSI.YEAR));
    /**
     * P removal rate, septic tank
     * <p/>
     * Value: 7
     * <p/>
     * Unit: %
     */
    public static final AmountDataSource P_removal_rate = new AmountDataSource<>(
            "p_removal",
            "P removal rate, septic tank",
            Amount.valueOf(7, NonSI.PERCENT));
    /**
     * N removal rate of septic tank (Naturvårdsverket 1985
     * <p/>
     * Value: 15
     * <p/>
     * Unit: %
     */
    public static final AmountDataSource N_removalrate = new AmountDataSource<>(
            "N_removalrate",
            "N removal rate of septic tank (Naturvårdsverket 1985",
            Amount.valueOf(15, NonSI.PERCENT));
    /**
     * BOD7 removal rate of septic tank (Naturvårdsverket 1985)
     * <p/>
     * Value: 15
     * <p/>
     * Unit: %
     */
    public static final AmountDataSource BOD7_removalrate = new AmountDataSource<>(
            "BOD7_removalrate",
            "BOD7 removal rate of septic tank (Naturvårdsverket 1985)",
            Amount.valueOf(15, NonSI.PERCENT));
    
    /**
     * Number of households on a Sewage Lorry working day
     * <p/>
     * Value: 20
     * <p/>
     * Unit: Hushåll
     */
    public static final AmountDataSource householdNrSewageLorry = new AmountDataSource<>(
            "households",
            "Number of households on a Sewage Lorry working day",
            Amount.valueOf(20, Unit.ONE));
}
